package org.jdcenter.server.xb.parser;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Element;
import org.jdcenter.face.PluginsConfig;
import org.jdcenter.server.xb.metadata.BeanMateData;
import org.jdcenter.server.xb.metadata.BeansMateData;
import org.jdcenter.server.xb.metadata.MateData;
import org.jdcenter.server.xb.metadata.MateDataException;
import org.jdcenter.server.xb.metadata.MateDataList;
import org.jdcenter.server.xb.metadata.ParameterMateData;
import org.jdcenter.server.xb.metadata.PluginsMateData;
/**
 * @author miao
 * @since 2008-11-27
 *
 */
public class PluginsParser<T extends MateData> extends AbstractParser{
	
	private static Log log = LogFactory.getLog(PluginsParser.class);

	@Override
	public MateData parseXML() {
		PluginsMateData pMateData = new PluginsMateData();
		pMateData.addMateData(parseBeanXML(pMateData));
		
		return pMateData;
	}
	
	public MateDataList parseBeanXML(PluginsMateData pMateData){	
		BeansMateData beansData = null;
		List<Element> beans = root.elements(beanTag);
		ClassLoader loader = Thread.currentThread().getContextClassLoader();
		if(beans != null && beans.size() > 0){
			beansData = new BeansMateData(pMateData);
			for(Element bean:beans){
				
				BeanMateData bMateData = new BeanMateData();
				String beanName = bean.attributeValue("name");
				checkStr(beanName,"name of bean");
				bMateData.setBeanName(beanName);
				
				String hotEdit = bean.attributeValue("hotEdit");
				if(hotEdit != null && hotEdit.equalsIgnoreCase("true")){
					System.setProperty(beanName, xmlURL.getPath());					
				}
				
				String className = bean.attributeValue("class");
				checkStr(className,"name of class");
				try {
					bMateData.setClazz(loader.loadClass(className));
				} catch (ClassNotFoundException e) {
					throw new ParserException(e);
				}
				Element constructor = bean.element("constructor");
				if(constructor != null){
					List<Element> parameters = constructor.elements("parameter");
					if(parameters != null){						
						List<ParameterMateData> constructorParameters = new ArrayList<ParameterMateData>();
						for(Element parameter:parameters){
							String type = parameter.attributeValue("type");
							checkStr(type,"type of parameter at constructor");
							String parameterValue = parameter.getTextTrim();
							
							if(!type.equalsIgnoreCase("String")){
								checkStr(parameterValue,"value of parameter at constructor");
							}
							
							constructorParameters.add(new ParameterMateData(type,parameterValue));
						}
						bMateData.setConstructorParameters(constructorParameters);
					}					
				}
				
				Element setter = bean.element("setter");
				if(setter != null){
					List<Element> parameters = setter.elements("parameter");
					if(parameters != null){						
						List<ParameterMateData> setterParameters = new ArrayList<ParameterMateData>();
						for(Element parameter:parameters){
							String type = parameter.attributeValue("type");
							checkStr(type,"type of parameter at setter");
							String parameterValue = parameter.getTextTrim();
							if(!type.equalsIgnoreCase("String")){
								checkStr(parameterValue,"value of parameter at setter");
							}
							
							setterParameters.add(new ParameterMateData(type,parameterValue));
						}
						bMateData.setSetterParameters(setterParameters);
					}					
				}
				Element start = bean.element("start");
				if(start != null){
					String startName = start.getTextTrim();
					checkStr(startName,"method to start");
					bMateData.setStartName(startName);
				}
				Element stop = bean.element("stop");
				if(stop != null){
					String stopName = stop.getTextTrim();
					checkStr(stopName,"method to stop");
					bMateData.setStopName(stopName);
				}
				Element dispose = bean.element("dispose");
				if(dispose != null){
					String disposeName = dispose.getTextTrim();
					checkStr(disposeName,"method to dispose");
					bMateData.setDisposeName(disposeName);
				}
				Element plugin = bean.element("plugin");
				if(plugin != null){
					String isPlugin = plugin.attributeValue("isPlugin");
					if(isPlugin != null && isPlugin.equalsIgnoreCase("true")){
						String isDefault = plugin.attributeValue("isDefault");
						String implType = plugin.attributeValue("implType");
						String pluginType = getPluginType(plugin);
						System.out.println(pluginType+"   "+implType);
						PluginsConfig.addPlugin(pluginType, implType, isDefault);
					}					
				}
				try {
					beansData.addMateData(bMateData);
				} catch (MateDataException e) {
					log.error(e);
				}
				
			}			
		}
		return beansData;
	}
	private void checkStr(String str,String name){
		if(str == null || str.length() == 0){
			throw ParserException.setNull(name);
		}
	}
	private String getPluginType(Element plugin){
		List<Element> pluginTypes = plugin.elements();
		if(pluginTypes != null && pluginTypes.size() > 0){
			for(Element pluginType : pluginTypes){
				if(pluginType.getTextTrim().equalsIgnoreCase("true")){
					return pluginType.getName();
				}
			}
		}
		return null;
	}
}
